package com.heima.article.service;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.heima.article.mapper.ApArticleMapper;
import com.heima.common.cache.CacheService;
import com.heima.common.constants.ArticleConstants;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.article.vos.HotArticleVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class HotArticleServiceImpl implements HotArticleService {

    @Autowired
    private ApArticleMapper apArticleMapper;

    @Autowired
    private CacheService cacheService;

    @Override
    public void computeHotArticle() {

        //查询前5天发布的文章
        LocalDateTime dateTime = LocalDateTime.now().minusDays(5);
        List<ApArticle> articleListByLast5days = apArticleMapper.findArticleListByLast5days(dateTime);
        if(CollectionUtils.isEmpty(articleListByLast5days)){
            return;
        }

        // 2.计算分值
        List<HotArticleVo> hotArticleVos = computeScore(articleListByLast5days);
        if(CollectionUtils.isEmpty(hotArticleVos)){
            return;
        }

        // 3.分组并缓存
        groupAndCache(hotArticleVos);
    }


    private void groupAndCache(List<HotArticleVo> hotArticleVos) {
        // 3.按频道分组缓存
        List<List<HotArticleVo>> listGroupByChannel = CollectionUtil.groupByField(hotArticleVos, "channelId");
        if (CollectionUtil.isEmpty(listGroupByChannel)) {
            return;
        }

        for (List<HotArticleVo> list : listGroupByChannel) {
            if (CollectionUtil.isEmpty(list)) {
                continue;
            }

            Integer channelId = list.get(0).getChannelId();

            sortedAndCache(list, ArticleConstants.HOT_ARTICLE_FIRST_PAGE + channelId.toString());
        }

        // 4.推荐分一组
        sortedAndCache(hotArticleVos, ArticleConstants.HOT_ARTICLE_FIRST_PAGE + ArticleConstants.DEFAULT_TAG);
    }

    private void sortedAndCache(List<HotArticleVo> hotArticleVos, String key) {
        if (CollectionUtils.isEmpty(hotArticleVos) || StringUtils.isEmpty(key)) {
            return;
        }

        hotArticleVos = hotArticleVos.stream().sorted(Comparator.comparing(HotArticleVo::getScore).reversed()).collect(Collectors.toList());

        // 截取30条
        if (hotArticleVos.size() > 30) {
            hotArticleVos = hotArticleVos.subList(0, 30);
        }

        cacheService.set(key, JSON.toJSONString(hotArticleVos));
    }


    public List<HotArticleVo> computeScore(List<ApArticle> list){
        if(CollectionUtils.isEmpty(list)){
            return new ArrayList<>();
        }

        ArrayList<HotArticleVo> voArrayList = new ArrayList<>();
        for (ApArticle apArticle : list) {
            if(apArticle == null){
                continue;
            }

            Integer views = apArticle.getViews();
            Integer likes = apArticle.getLikes();
            Integer comment = apArticle.getComment();
            Integer collection = apArticle.getCollection();
            Integer score = 0;

            if(views != null){
                score += views;
            }

            if (likes != null) {
                score += (ArticleConstants.HOT_ARTICLE_LIKE_WEIGHT * likes);
            }

            if (comment != null) {
                score += (ArticleConstants.HOT_ARTICLE_COMMENT_WEIGHT * comment);
            }

            if (collection != null) {
                score += (ArticleConstants.HOT_ARTICLE_COLLECTION_WEIGHT * collection);
            }

            HotArticleVo hotArticleVo = new HotArticleVo();
            BeanUtils.copyProperties(apArticle,hotArticleVo);
            hotArticleVo.setScore(score);

            voArrayList.add(hotArticleVo);
        }
        return voArrayList;
    }
}
